import math

"""
这段代码是一个计算用户相似度的函数，基于用户的协同过滤算法。

函数的输入参数train是一个字典，表示用户与物品的评分训练集。字典的键是用户ID，对应的值是另一个字典，表示该用户对不同物品的评分。函数的输出是一个字典W，表示用户之间的相似度。

代码的运行过程如下：

创建一个空字典item_users，用于存储每个物品被哪些用户评分过（倒排索引）。
遍历训练集train中的每个用户及其对应的评分信息。
对于每个用户u，遍历其评分过的每个物品i。
如果物品i不在item_users中，将其加入，并初始化对应的值为一个空的集合。
将用户u加入到物品i对应的集合中，表示物品i被用户u评分过。
创建两个空字典C和N，分别用于统计共现矩阵和用户评分物品的次数。
再次遍历item_users中的每个物品及其对应的评分用户集合。
对于每个物品i，遍历其评分过的每个用户u。
增加用户u的评分物品次数，即N[u] += 1。
对于物品i的每个评分用户v（除去用户u本身），增加C[u][v]的值（默认为0）。
创建空字典W，用于存储用户之间的相似度。
再次遍历C中的每个用户及其相关用户。
对于每对用户u和v及其共现次数C[u][v]，计算相似度W[u][v] = C[u][v] / sqrt(N[u] * N[v])。
将相似度存储在W[u][v]中。
返回计算得到的相似度字典W。
需要注意的是，代码中使用了一些未定义的字典变量C、N和W，在调用函数前应该先进行初始化。
"""

import math


def Usersimilarity(train):
    item_users = dict()
    # 倒排索引
    for u, items in train.items():
        for i in items.keys():
            if i not in item_users:
                item_users[i] = set()
            item_users[i].add(u)

    C = dict()
    N = dict()
    # 共现矩阵
    for i, users in item_users.items():
        for u in users:
            if u not in N:
                N[u] = 0
            N[u] += 1
            if u not in C:
                C[u] = dict()
            for v in users:
                if u == v:
                    continue
                if v not in C[u]:
                    C[u][v] = 0
                C[u][v] += 1

    W = dict()
    for u, related_users in C.items():
        if u not in W:
            W[u] = dict()
        for v, cuv in related_users.items():
            W[u][v] = cuv / math.sqrt(N[u] * N[v])

    return W


if __name__ == '__main__':
    # 创建测试数据
    train_data = {
        'user1': {'item1': 5, 'item2': 3, 'item4': 2},
        'user2': {'item1': 3, 'item3': 4},
        'user3': {'item2': 4, 'item3': 1, 'item5': 5},
        'user4': {'item1': 2, 'item2': 5, 'item4': 1, 'item5': 4},
        'user5': {'item1': 1, 'item3': 2, 'item5': 3}
    }

    # 计算用户相似度
    similarity_matrix = Usersimilarity(train_data)

    # 输出相似度矩阵
    for user1, sim_users in similarity_matrix.items():
        for user2, similarity in sim_users.items():
            print(f"用户{user1}和用户{user2}的相似度: {similarity:.2f}")
